home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 January: Mac OS SDK / Dev.CD Jan 98 SDK1.toast / Development Kits (Disc 1) / QuickDraw 3D / Samples / SampleCode / Unsupported Libraries / QDUtils.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-08-14  |  11.6 KB  |  477 lines  |  [TEXT/MPS ]

  1. /******************************************************************************
  2.  **                                                                             **
  3.  **     Module:        QDUtils.c                                                 **
  4.  **                                                                          **
  5.  **                                                                          **
  6.  **     Purpose:     Utilities for creating Quickdraw windows and GWorlds     **
  7.  **                                                                          **
  8.  **                                                                          **
  9.  **                                                                          **
  10.  **     Copyright (C) 1992-1996 Apple Computer, Inc.  All rights reserved.     **
  11.  **                                                                          **
  12.  **                                                                          **
  13.  *****************************************************************************/
  14. #include <Script.h>
  15. #include <stdio.h>
  16.  
  17. #include <Memory.h>
  18. #include <Quickdraw.h>
  19. #include <QDOffscreen.h>
  20. #include <Windows.h>
  21.  
  22. #include "QD3D.h"
  23. #include "QDUtils.h"
  24.  
  25. /******************************************************************************
  26.  **                                                                             **
  27.  **                                    Macros                                     **
  28.  **                                                                             **
  29.  *****************************************************************************/
  30.  
  31. /* a bad hack macro */
  32. #ifndef GetMBarHeight
  33. #define GetMBarHeight() (* (short *) 0x0BAA)
  34. #endif
  35.  
  36. #define COPYRECT(srcRect, dstRect) {                             \
  37.             *(long *)(dstRect)     = *(long *)(srcRect);         \
  38.             ((long *)(dstRect))[1] = ((long *)(srcRect))[1];     \
  39.         }
  40.  
  41.  
  42. /******************************************************************************
  43.  **                                                                             **
  44.  **                            Forward Declarations                             **
  45.  **                                                                             **
  46.  *****************************************************************************/
  47.  
  48. static GDHandle GetGDeviceUsingDepth(
  49.     unsigned long    depth);
  50.  
  51. static GDHandle FindDeviceFromWindow(
  52.     WindowPtr         window,
  53.     PixMapHandle    gPixMap);
  54.  
  55. static void GetPortTopLeft(
  56.     CGrafPtr         port, 
  57.     Point             *topLeft);
  58.  
  59. static BitMap *BitsToMap(
  60.     BitMap             *bits);
  61.  
  62. static void CopyPixels_32(
  63.     GDHandle        device,
  64.     WindowPtr        window,
  65.     PixMapHandle    hPixMap);
  66.  
  67.  
  68. /******************************************************************************
  69.  **                                                                             **
  70.  **                                    Functions                                 **
  71.  **                                                                             **
  72.  *****************************************************************************/
  73.  
  74. /*===========================================================================*\
  75.  *
  76.  *    Routine:    QDWindow_New()
  77.  *
  78.  *    Comments:    Create a Quickdraw window and return it.  The window is
  79.  *                centered in the gdevice that has the specified depth or
  80.  *                the device with the greatest depth less than said depth.
  81.  *                This is an application-specific function.
  82.  *
  83. \*===========================================================================*/
  84.  
  85. WindowPtr QDWindow_New(
  86.     Str255            name,
  87.     unsigned long    x,
  88.     unsigned long    y,
  89.     unsigned long    xSize, 
  90.     unsigned long    ySize, 
  91.     unsigned long    depth,
  92.     TQ3Boolean        autoCenter)
  93. {
  94.     Rect            deviceBounds;
  95.     unsigned short    xCenter;
  96.     unsigned short    yCenter;
  97.     Rect            where;
  98.     GDHandle        gDevice;
  99.     WindowPtr        window;
  100.  
  101.     gDevice = GetGDeviceUsingDepth(depth);
  102.     deviceBounds = (*gDevice)->gdRect;
  103.     
  104.     if (autoCenter) {
  105.         xCenter = deviceBounds.left + 
  106.                     ((deviceBounds.right - deviceBounds.left)/2);
  107.         yCenter = deviceBounds.top + 
  108.                     ((deviceBounds.bottom - deviceBounds.top)/2);
  109.         yCenter += (GetMBarHeight()/2);
  110.     
  111.         where.left         = xCenter - (xSize/2);
  112.         where.top         = yCenter - (ySize/2);
  113.     } else {
  114.         where.left         = x;
  115.         where.top         = y;
  116.     }
  117.  
  118.     where.right     = where.left + xSize;
  119.     where.bottom     = where.top + ySize;
  120.  
  121.     window = NewCWindow(nil, 
  122.                         &where, 
  123.                         name, 
  124.                         true, 
  125.                         documentProc, 
  126.                         (WindowPtr) -1, 
  127.                         false, 
  128.                         0);
  129.     if (!window) {
  130.         return (NULL);
  131.     }
  132.     
  133.     SetPort(window);
  134.     
  135.     return (window);
  136. }
  137.  
  138.  
  139. /*===========================================================================*\
  140.  *
  141.  *    Routine:    GetGDeviceUsingDepth()
  142.  *
  143.  *    Comments:    Find the gdevice that best fits the depth argument.  If not
  144.  *                found then return the first gdevice.
  145.  *
  146.  *    Notes:        This is an application-specific function.
  147.  *
  148. \*===========================================================================*/
  149.  
  150. static GDHandle GetGDeviceUsingDepth(
  151.     unsigned long    depth)
  152. {
  153.     GDHandle        device;                /* current device */
  154.     GDHandle        bestDevice;            /* device close to matching depth */
  155.     unsigned long    bestDeviceNotFound;    /* termination flag */
  156.  
  157.     bestDevice = device = GetDeviceList();
  158.     bestDeviceNotFound = 1;
  159.  
  160.     while (bestDeviceNotFound && device) {
  161.         /* only search on active screen devices */
  162.         if (((*device)->gdFlags & (1 << screenActive)) == 0) {
  163.             continue;
  164.         }
  165.  
  166.         if ((*(*device)->gdPMap)->pixelSize == depth) {
  167.             bestDevice = device;
  168.             bestDeviceNotFound = 0;
  169.         }
  170.         
  171.         device = GetNextDevice(device);
  172.     }
  173.  
  174.     return (bestDevice);
  175. }
  176.  
  177.  
  178. /*===========================================================================*\
  179.  *
  180.  *    Routine:    QDGWorld_New()
  181.  *
  182.  *    Comments:    Create a Quickdraw window and return it.  The window is
  183.  *                centered in the gdevice that has the specified depth or
  184.  *                the device with the greatest depth less than said depth.
  185.  *                This is an application-specific function.
  186.  *
  187. \*===========================================================================*/
  188.  
  189. GWorldPtr QDGWorld_New(
  190.     unsigned long    xSize, 
  191.     unsigned long    ySize, 
  192.     unsigned long    depth)
  193. {
  194.     Rect            rectGW;
  195.     GWorldPtr        gWorld;
  196.     PixMapHandle     hPixMap;
  197.     
  198.     SetRect(&rectGW, 0, 0, (unsigned short)xSize, (unsigned short)ySize);
  199.     NewGWorld(&gWorld, depth, &rectGW, 0, 0, 0);
  200.     
  201.     if(gWorld == NULL)
  202.         return(NULL);
  203.  
  204.     hPixMap = GetGWorldPixMap(gWorld);
  205.     HLock((Handle)hPixMap);
  206.  
  207.     LockPixels(hPixMap);
  208.  
  209.     HUnlock((Handle)hPixMap);
  210.     
  211.     return (gWorld);
  212. }
  213.  
  214.  
  215. /*===========================================================================*\
  216.  *
  217.  *    Routine:    QDClearBackground()
  218.  *
  219.  *    Comments:    This is an application-specific function.
  220.  *
  221. \*===========================================================================*/
  222.  
  223. void QDClearBackground(
  224.     GWorldPtr    gWorld,
  225.     TQ3ColorRGB    bgColor)
  226. {
  227.     RGBColor    qdBgColor;
  228.     GrafPtr        port;
  229.  
  230.     if (gWorld) {
  231.         GDHandle    oldGD;
  232.         GWorldPtr    oldGW;
  233.  
  234.         /* save current port */
  235.         GetGWorld(&oldGW, &oldGD);
  236.  
  237.         SetGWorld(gWorld, NULL);
  238.         qdBgColor.red     = (unsigned short)(bgColor.r * 65535.0);
  239.         qdBgColor.green = (unsigned short)(bgColor.g * 65535.0);
  240.         qdBgColor.blue     = (unsigned short)(bgColor.b * 65535.0);
  241.         RGBBackColor(&qdBgColor);
  242.         EraseRect(&gWorld->portRect);
  243.         
  244.         /* restore port */
  245.         SetGWorld(oldGW, oldGD);
  246.     } else {
  247.         qdBgColor.red     = (unsigned short)(bgColor.r * 65535.0);
  248.         qdBgColor.green = (unsigned short)(bgColor.g * 65535.0);
  249.         qdBgColor.blue     = (unsigned short)(bgColor.b * 65535.0);
  250.         RGBBackColor(&qdBgColor);
  251.         GetPort(&port);
  252.         EraseRect(&port->portRect);
  253.     }
  254. }
  255.  
  256.  
  257. /*===========================================================================*\
  258.  *
  259.  *    Routine:    QDSwapBuffer()
  260.  *
  261.  *    Comments:    If there is a gWorld then copy from it to the window.
  262.  *                This is an application-specific function.
  263.  *
  264. \*===========================================================================*/
  265.     
  266. void QDSwapBuffer(
  267.     WindowPtr    window,
  268.     GWorldPtr    gWorld)
  269. {
  270.     if (window && gWorld) {
  271.         PixMapHandle     hPixMap;
  272.         GrafPtr            savePort;
  273.         RGBColor        qdBgColor;
  274.         
  275.         GetPort(&savePort);
  276.         SetPort(window);
  277.         
  278.         hPixMap = GetGWorldPixMap(gWorld);
  279.         HLock((Handle)hPixMap);
  280.  
  281.         qdBgColor.red     = (unsigned short)65535;
  282.         qdBgColor.green = (unsigned short)65535;
  283.         qdBgColor.blue     = (unsigned short)65535;
  284.         RGBBackColor(&qdBgColor);
  285.  
  286.         /* myGDevice = FindDeviceFromWindow(window, hPixMap); */
  287.         /* CopyPixels_32(myGDevice, window, hPixMap); */
  288.         CopyBits((BitMapPtr)(*hPixMap), 
  289.                  (BitMapPtr) &window->portBits,
  290.                  (Rect *) &(*gWorld).portRect,
  291.                  (Rect *) &window->portRect,
  292.                  (short)srcCopy, (RgnHandle)NULL);    
  293.  
  294.         HUnlock((Handle)hPixMap);
  295.         
  296.         SetPort(savePort);
  297.     }
  298. }
  299.  
  300. /*===========================================================================*\
  301.  *
  302.  *    Routine:    CopyPixels_32()
  303.  *
  304.  *    Comments:
  305.  *
  306. \*===========================================================================*/
  307.  
  308. static void CopyPixels_32(
  309.     GDHandle        device,
  310.     WindowPtr        window,
  311.     PixMapHandle    hPixMap)
  312. {
  313.     long            w, width, height;
  314.     Point            upperLeft;
  315.     Rect            deviceBounds;
  316.     long            offsetX, offsetY;
  317.     unsigned long    *srcPtr, *srcStart, *dstPtr, *dstStart;
  318.     long            srcRowBytes, dstRowBytes;
  319.  
  320.     width = (*hPixMap)->bounds.right - (*hPixMap)->bounds.left;
  321.     height = (*hPixMap)->bounds.bottom - (*hPixMap)->bounds.top;
  322.  
  323.     upperLeft.v = window->portRect.top;
  324.     upperLeft.h = window->portRect.left;
  325.     LocalToGlobal(&upperLeft);
  326.  
  327.     deviceBounds = (*device)->gdRect;
  328.     offsetX = upperLeft.h - deviceBounds.left;    
  329.     offsetY = upperLeft.v - deviceBounds.top;
  330.  
  331.     srcRowBytes = (*hPixMap)->rowBytes & 0x3FFF;
  332.     dstRowBytes = (*(*device)->gdPMap)->rowBytes & 0x3FFF;
  333.     
  334.     srcStart = (unsigned long *)(*hPixMap)->baseAddr;
  335.  
  336.     dstStart = (unsigned long *)((unsigned char *)((*(*device)->gdPMap)->baseAddr) +
  337.         (offsetY * dstRowBytes) + (offsetX << 2));
  338.  
  339.     while (--height >= 0) {
  340.         w = width;
  341.  
  342.         srcPtr = srcStart;
  343.         dstPtr = dstStart;
  344.  
  345.         while (--w >= 0) {
  346.             *dstPtr++ = *srcPtr++;
  347.         }
  348.  
  349.         srcStart = (unsigned long *)((unsigned char *)srcStart + srcRowBytes);
  350.         dstStart = (unsigned long *)((unsigned char *)dstStart + dstRowBytes);
  351.     }
  352. }
  353.  
  354. /*===========================================================================*\
  355.  *
  356.  *    Routine:    FindDeviceFromWindow()
  357.  *
  358.  *    Comments:
  359.  *
  360. \*===========================================================================*/
  361.  
  362. static GDHandle FindDeviceFromWindow(
  363.     WindowPtr         window,
  364.     PixMapHandle     hPixMap)
  365. {
  366.     GDHandle        device;            /* current device */
  367.     Rect            devBox;            /* local coords of device intersected with drawBox */
  368.     Point            topLeft;        /* topLeft of current port */
  369.     RgnHandle        devRgn;            /* region for device rectangle */
  370.     RgnHandle        drawRgn;        /* region for draw box */
  371.     RgnHandle        dstRgn;            /* intersect of drawing and device regions */
  372.     Rect            drawBox;        /* drawing rectangle */
  373.  
  374.     if (!window) {
  375.         return (NULL);
  376.     }
  377.  
  378.     devRgn = NewRgn();
  379.     HLock((Handle)devRgn);
  380.     drawRgn = NewRgn();
  381.     HLock((Handle)drawRgn);
  382.     dstRgn = NewRgn();
  383.     HLock((Handle)dstRgn);
  384.     
  385.     drawBox = window->portRect;
  386.  
  387.     GetPortTopLeft((CGrafPtr)window, &topLeft);
  388.     SetRectRgn(drawRgn, 
  389.                drawBox.left, drawBox.top, 
  390.                drawBox.right, drawBox.bottom);
  391.     
  392.     device = GetDeviceList();
  393.  
  394.     while (device) {
  395.         if (((*device)->gdFlags & (1 << screenActive))) {
  396.             /* convert the device rect to local coordinates */
  397.             COPYRECT(&(*device)->gdRect, &devBox);
  398.             devBox.top    -= topLeft.v;
  399.             devBox.left   -= topLeft.h;
  400.             devBox.bottom -= topLeft.v;
  401.             devBox.right  -= topLeft.h;
  402.             
  403.             /* test for intersection */
  404.             SetRectRgn(devRgn, 
  405.                        devBox.left, devBox.top, 
  406.                        devBox.right, devBox.bottom);
  407.             SectRgn(devRgn, drawRgn, dstRgn);
  408.  
  409.             if (!EmptyRgn(dstRgn)) {
  410.                 PixMapHandle    gdPMap;
  411.                 
  412.                 gdPMap = (*device)->gdPMap;
  413.                 if ((*gdPMap)->pixelSize == (*hPixMap)->pixelSize) {
  414.                     goto GetOutOfThisFunction;
  415.                 }
  416.  
  417.             }
  418.         }
  419.  
  420.         device = GetNextDevice(device);
  421.         
  422.     }
  423.         
  424. GetOutOfThisFunction:
  425.  
  426.     HUnlock((Handle)devRgn);
  427.     HUnlock((Handle)drawRgn);
  428.     HUnlock((Handle)dstRgn);
  429.     DisposeRgn(devRgn);
  430.     DisposeRgn(dstRgn);
  431.     DisposeRgn(drawRgn);
  432.     
  433.     return (device);
  434. }
  435.  
  436.  
  437. /*===========================================================================*\
  438.  *
  439.  *    Routine:    GetPortTopLeft(port, topLeft)
  440.  *
  441.  *    Comments:    returns the 0,0 of the port in global coordinates
  442.  *
  443. \*===========================================================================*/
  444.  
  445. static void GetPortTopLeft(
  446.     CGrafPtr     port, 
  447.     Point         *topLeft)
  448. {
  449.     BitMap         *bits;
  450.     
  451.     bits = BitsToMap(&((GrafPtr) port)->portBits);
  452.     
  453.     topLeft->v = - bits->bounds.top;
  454.     topLeft->h = - bits->bounds.left;
  455. }
  456.  
  457.  
  458. /*===========================================================================*\
  459.  *
  460.  *    Routine:    BitsToMap(bits)
  461.  *
  462.  *    Comments:    If bits is the address of portBits of a cgrafport then
  463.  *                convert it to a pointer to the port's pix map.
  464.  *
  465. \*===========================================================================*/
  466.  
  467. static BitMap *BitsToMap(
  468.     BitMap     *bits)
  469. {
  470.     if (((BitMap *)bits)->rowBytes < 0 &&
  471.         ((BitMap *)bits)->rowBytes & (1 << 14)) {
  472.         bits = *(BitMap **) bits->baseAddr;
  473.     }
  474.     
  475.     return bits;
  476. }
  477.